import multiprocessing
import time
import os

# 进程之间不共享全局变量
# 因为创建一个子进程其实是对主进程的拷贝
val = 0


def dance():
    # 获取当前进程（跳舞进程进程）编号
    print('跳舞进程编号：', os.getpid())
    # 获取父进程编号
    print('跳舞进程父进程编号',os.getppid())
    for i in range(3):
        print('跳舞进程')
        global val
        val += 1
        print('跳舞进程value值：', val)
        time.sleep(0.2)


def sing():
    # 获取当前进程（唱歌进程）编号
    sing_id = os.getpid()
    print('唱歌进程编号：', sing_id)
    # 获取父进程编号
    print('唱歌进程父进程编号', os.getppid())
    for i in range(3):
        print('唱歌进程')
        global val
        val += 1
        print('唱歌进程value值：', val)
        time.sleep(0.2)
        # 强制杀死唱歌进程，使其只执行一次
        os.kill(sing_id, 9)


def show_info(name, age):
    print(name, age)



# 提示:.对应linux和mac主进程执行的代码不会进程拷贝，但是对应window系统来说主进程执行的代码也会进行拷贝执行
# 对于window来说创建子进程的代码如果进程拷贝执行相当于递归无限制进行创建子进程，会报错
# 如何解决windows递归创建子进程﹐通过判断是否是主模块来解决
if __name__ == '__main__':
    # group进程组目前只能写None,省略不写就是None
    # target是进程要执行的任务
    # name如果不指定进程名字就会自动为Process-1...
    dance_process = multiprocessing.Process(target=dance)
    sing_process = multiprocessing.Process(target=sing)
    # 带有参数进程（可以元组传参数也可以字典传参）
    # 以元组方式传参要保证顺序一致 以字典方式传参要保证名称一致
    show_process = multiprocessing.Process(target=show_info, args=('xiaohong',), kwargs={'age': '11'})

    # 获取当前进程（主进程）编号
    print('主进程编号：', os.getpid())
    # # 设置子进程为守护进程
    # dance_process.daemon = True
    # sing_process.daemon = True
    # show_process.daemon = True

    dance_process.start()
    sing_process.start()
    show_process.start()
    # 主进程会等所有子进程都结束了再结束
    # 设置主进程执行0.2s后退出
    # 设置子进程为守护进程，主进程退出子进程销毁，子进程依赖主进程
    # 主进程退出前销毁子进程
    time.sleep(0.2)
    dance_process.terminate()
    sing_process.terminate()
    show_process.terminate()
    print('over')

# 进程之间执行是无序的，顺序由操作系统调度来决定
# 和计算密集型的相关操作使用多进程
